热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

纵坐标|据点_菜菜的sklearn课堂笔记支持向量机线性SVM决策过程的可视化

篇首语:本文由编程笔记#小编为大家整理,主要介绍了菜菜的sklearn课堂笔记支持向量机-线性SVM决策过程的可视化相关的知识,希望对你有一定的参考价值。 我们可以使用

篇首语:本文由编程笔记#小编为大家整理,主要介绍了菜菜的sklearn课堂笔记支持向量机-线性SVM决策过程的可视化相关的知识,希望对你有一定的参考价值。



我们可以使用sklearn中的式子来为可视化我们的决策边界,支持向量,以及决策边界平行的两个超平面。

from sklearn.datasets import make_blobs
from sklearn.svm import SVC
import matplotlib.pyplot as plt
import numpy as np

X, y = make_blobs(n_samples=50,centers=2,random_state=0,cluster_std=0.6)
X.shape # 因为我们指定要50个样本,方法本身默认两个维度,因此样本矩阵的shape为(50,2)
---
(50, 2)
y.shape
---
(50,)
set(y) # 生成不同类样本的标签默认0,1,2……排列,这里指定两个中心,也就是两类,一次y的取值为1,2
---
0, 1
plt.scatter(X[:,0],X[:,1],c=y,s=50,cmap=rainbow)
# 这里告诉我们,color是支持非负正数array作为参数值的
plt.xticks([])
plt.yticks([])
plt.show()

画决策边界:理解函数contour
Contour是我们专门用来绘制等高线的函数。等高线,本质上是在二维图像上表现三维图像的一种形式,其中两维X和Y是两条坐标轴上的取值,而Z表示高度。Contour就是将由X和Y构成平面上的所有点中,高度一致的点连接成线段的函数,在同一条等高线上的点一定具有相同的Z值。我们可以利用这个性质来绘制我们的决策边界。

contour([X, Y,] Z, [levels], **kwargs)
---
# X, Y:选填。两维平面上所有的点的横纵坐标取值,一般要求是二维结构并且形状需要与Z相同(因为坐标要与Z值意义对应),往往通过numpy.meshgrid()这样的函数来创建。
# 这一段可以先不看,不太好理解(其实我根本就没理解这一段)。如果X和Y都是一维,则Z的结构必须为(len(Y), len(X))。如果不填写,则默认X = range(Z.shape[1]),Y = range(Z.shape[0])。
# Z:必填。平面上所有的点所对应的高度。
# levels:可不填,不填默认显示所有的等高线,填写用于确定等高线的数量和位置。如果填写整数n,则显示n个数据区间,即绘制n+1条等高线。水平高度自动选择。如果填写的是数组或列表,则在指定的高度级别绘制等高线。列表或数组中的值必须按递增顺序排列。

我们的决策边界是$\\omega \\cdot x+b=0$,并在决策边界的两边找出两个超平面,使得超平面到决策边界的相对距离为1。那其实,我们只需要在我们的样本构成的平面上,把所有到决策边界的距离为0的点相连,就是我们的决策边界,而把所有到决策边界的相对距离为1的点相连,就是我们的两个平行于决策边界的超平面了。此时,我们的Z就是平面上的任意点到达超平面的距离

那首先,我们需要获取样本构成的平面,作为一个对象。

# 首先要有散点图,因为我们要获得axis对象来获得xlim,ylim
plt.scatter(X[:,0],X[:,1],c=y,s=50,cmap=rainbow)
ax = plt.gca() # 获取当前的子图,如果不存在,就创建新的子图
# 这里有图,就不再重复了,和上面的散点图一样
ax # axes对象,就是那个框
---

# 获取平面上两条坐标轴的最大值和最小值
xlim = ax.get_xlim()
ylim = ax.get_ylim()
xlim # 所有数据点x的最大值和最小值
---
(-0.7541740493109252, 3.3838081780236036)
ylim # 所有数据点y的最大值和最小值
---
(-0.43660961990940284, 5.772756283035797)
# 在最大值和最小值(含两端)之间形成30个规律的数据
# 这也就决定着我们meshgrid的结果应该是一个30*30的矩阵
axisx = np.linspace(xlim[0],xlim[1],30)
axisy = np.linspace(ylim[0],ylim[1],30)
axisx
# arrax里的元素,从小到大排列,最小值即为数据点x的最小值,最大值即为数据点x的最大值
# 这个可以认为是一个列向量
---
array([-0.75417405, -0.61148501, -0.46879596, -0.32610692, -0.18341788,……, 3.38380818]) # 中间截掉了
axisx.shape
---
(30,)
axisy, axisx = np.meshgrid(axisy,axisx) # 注意对应关系,别把x,y弄反了,要换一起换
# meshgrid函数将两个一维向量转换为特征矩阵
# 核心是两个特征向量的广播,以便获取y.shape * x.shape数量个坐标点的横坐标和纵坐标
axisx.shape
# 对于axisx来说,是一个30*30的矩阵,第i行是之前array的第i-1个元素(因为有第0个元素,但没有第0行)
# 对于x来说,同一行的元素相同
---
(30, 30)
axisx[0]
---
array([-0.75417405, -0.75417405, -0.75417405, -0.75417405, -0.75417405,…… , -0.75417405])
axisy[:,0] # 对y来说,同一列的元素相同
---
array([-0.43660962, -0.43660962, -0.43660962, -0.43660962, -0.43660962,……, -0.43660962])

xy = np.vstack([axisx.ravel(), axisy.ravel()]).T
# xy就是已经形成的网格,它是遍布在整个画布上密集的点
xy.shape
# 两列也就是两个维度,第一列是x坐标,第二列是y坐标
# 900说明有900个点
---
(900, 2)
xy # ravel的时候x在前面,并且x每一行是同一个数值,因此这里的xy,第一列对应的就是之前的x,且每30个元素聚在一起都是一样的,然后后面y从小到大的取值不断重复与x进行匹配
---
array([[-0.75417405, -0.43660962],
[-0.75417405, -0.22249355],
[-0.75417405, -0.00837749],
...,
[ 3.38380818, 5.34452415],
[ 3.38380818, 5.55864022],
[ 3.38380818, 5.77275628]])
plt.scatter(xy[:,0],xy[:,1],s=1,cmap=rainbow)
# 可视化来看xy里每一行就是一个点,并且这个点的顺序是从最左边的x开始,y从最下边开始,y逐渐向上增大,到最大后,x向右移动一个值,y回到最小值,重复上述操作,直到x,y都到最大值

有了网格后,我们需要计算网格所代表的“平面上所有的点”到我们的决策边界的距离。所以我们需要我们的模型和决策边界。

clf = SVC(kernel="linear").fit(X,y)# 实例化,实际上就是计算得到决策边界
# X是数据矩阵,y是样本标签
Z = clf.decision_function(xy).reshape(axisx.shape)
# 重要接口decision_function,返回每个输入样本所对应的到决策边界的距离
# 这里输入样本就是上面的矩阵散点,距离指的是几何距离
# 这里reshape要注意一点,由于我们这xy里点的顺序是先从下到上,然后从左到右,也就是scatter可视化的时候说的顺序
# 因此clf.decision_function(xy).shape得到的距离array每个元素对应的点顺序也是从下到上,从左到右,同scatter可视化的时候说的顺序,只不过现在只有一列
# reshape这个array之后得到的Z矩阵元素第一行从左到右实际上是上面散点矩阵第一列从下到上点到决策边界的距离,同scatter可视化的时候说的顺序,只不过这里变成了30*30,只要注意顺序就行
# 一个小知识点,reshape可以传入元组
clf.decision_function(xy).shape
# xy有900个点,因此返回距离也有900个
---
(900,)
Z.shape
---
(30, 30)
plt.scatter(X[:,0],X[:,1],c=y,s=50,cmap=rainbow)
ax = plt.gca() # 获取当前的子图,如果不存在,就创建新的子图
# 这两行必须写上,不然画不出图,因为没有plt.scatter我们就没有画布,我们只是操作了ax对象
ax.contour(axisx,axisy,Z
,colors=k
,levels=[-1,0,1] # 画三条等高线,分别是Z为-1,0,1的三条线
,alpha=0.5
,linestyles=[--,-,--]
)
# 关于上面的一句话
# reshape这个array之后得到的Z矩阵元素第一行从左到右实际上是上面散点矩阵第一列从下到上点到决策边界的距离
# 其实也很好理解
# 我们取axisx的第1行第1列的元素,为-0.75417405,axisy的第1行第1列的元素,为-0.43660962,Z的第1行第1列的元素,为该点到决策边界的距离
# 同一第1行第2列的元素同理,由axisx,axisy得到的坐标应该是(-0.75417405,-0.22249355),对应Z第1行第2列的元素也是该点到决策边界的距离
# 这也就是说,axisx,axisy,Z三个矩阵,对应元素组合起来是有意义的
ax.set_xlim(xlim)
ax.set_ylim(ylim)
# 这里需要注意的是,上面的虚线超平面对应相对距离为-1,下面的虚线超平面对应相对距离为1

Z[0]
# 对应我们Z的第一行,也就是横坐标为-0.75417405,纵坐标从小变大点到决策边界的距离
# 显然两头数值大,离决策边界远,中间接近,甚至有0值,上面的可视化就能验证
---
array([ 3.61796573, 3.32300315, 3.02804058, 2.73307801, 2.43811544, 2.14315287, 1.8481903 , 1.55322772, 1.25826515, 0.96330258, 0.66834001, 0.37337744, 0.07841487, -0.21654771, -0.51151028, -0.80647285, -1.10143542, -1.39639799, -1.69136056, -1.98632313, -2.28128571, -2.57624828, -2.87121085, -3.16617342, -3.46113599, -3.75609856, -4.05106114, -4.34602371, -4.64098628, -4.93594885])

进一步理解,我们要画过某点平行于决策边界的超平面

distance = clf.decision_function(X[10].reshape(1,-1))
# 由于decision_function接口只接受二维数据,而X[10]返回array([1.71444449, 5.02521524])为一维数据,因此考虑reshape(1,-1)
plt.scatter(X[:,0],X[:,1],c=y,s=50,cmap="rainbow")
plt.scatter(X[10,0],X[10,1],c=black,s=50)
ax = plt.gca()
ax.contour(axisx,axisy,Z
,colors=k
,levels=[distance]
,alpha=0.5
,linestyles=[--]
)

我们再回看上面绘制决策边界的过程,发现我们只需要模型和散点图的边框就可以得到可视化的决策边界。因此,我们可视化决策边界的过程进行包装

def plot_svc_decision_function(model,ax=None):
if ax is None:
ax = plt.gca()

xlim = ax.get_xlim()
ylim = ax.get_ylim()
x = np.linspace(xlim[0],xlim[1],30)
y = np.linspace(ylim[0],ylim[1],30)
Y,X = np.meshgrid(y,x)
xy = np.vstack([X.ravel(),Y.ravel()]).T
P = model.decision_function(xy).reshape(X.shape)
ax.contour(X,Y,P,colors=k,levels=[-1,0,1],alpha=0.5,linestyles=[--,-,--])
ax.set_xlim(xlim)
ax.set_ylim(ylim)

clf = SVC(kernel="linear").fit(X,y)
plt.scatter(X[:,0],X[:,1],c=y,s=50,cmap="rainbow")
# 这两行和吉祥物一样
plot_svc_decision_function(clf)
plt.contour()

探索建好的模型

clf.predict(X)
# 根据决策边界,对X中的样本进行分类,返回结构为n_samples
---
array([1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0])
clf.score(X,y)
# 返回给定测试集数据和标签的平均准确度
# 因为这里我们建立线性SVM的时候用的就是可分的样本集,再用样本集进行测试,因此score一定为1
---
1.0
clf.support_vectors_# 返回支持向量,不一定只有两个
---
array([[0.44359863, 3.11530945],
[2.33812285, 3.43116792],
[2.06156753, 1.96918596]])
clf.n_support_# 返回每个类中支持向量的个数
---
array([2, 1])

推荐阅读
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • golang常用库:配置文件解析库/管理工具viper使用
    golang常用库:配置文件解析库管理工具-viper使用-一、viper简介viper配置管理解析库,是由大神SteveFrancia开发,他在google领导着golang的 ... [详细]
  • Android 渐变圆环加载控件实现
    本文介绍了如何在 Android 中创建一个自定义的渐变圆环加载控件,该控件已在多个知名应用中使用。我们将详细探讨其工作原理和实现方法。 ... [详细]
  • 将Web服务部署到Tomcat
    本文介绍了如何在JDeveloper 12c中创建一个Java项目,并将其打包为Web服务,然后部署到Tomcat服务器。内容涵盖从项目创建、编写Web服务代码、配置相关XML文件到最终的本地部署和验证。 ... [详细]
  • Python 异步编程:深入理解 asyncio 库(上)
    本文介绍了 Python 3.4 版本引入的标准库 asyncio,该库为异步 IO 提供了强大的支持。我们将探讨为什么需要 asyncio,以及它如何简化并发编程的复杂性,并详细介绍其核心概念和使用方法。 ... [详细]
  • Søren Kierkegaard famously stated that life can only be understood in retrospect but must be lived moving forward. This perspective delves into the intricate relationship between our lived experiences and our reflections on them. ... [详细]
  • PyCharm中配置Pylint静态代码分析工具
    本文详细介绍如何在PyCharm中配置和使用Pylint,帮助开发者进行静态代码检查,确保代码符合PEP8规范,提高代码质量。 ... [详细]
  • 本文介绍如何使用Objective-C结合dispatch库进行并发编程,以提高素数计数任务的效率。通过对比纯C代码与引入并发机制后的代码,展示dispatch库的强大功能。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 本文详细介绍了如何使用 Yii2 的 GridView 组件在列表页面实现数据的直接编辑功能。通过具体的代码示例和步骤,帮助开发者快速掌握这一实用技巧。 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
author-avatar
liaojiawei
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有